#include "dxManager.h"

DxManager::DxManager(void)
{
	pD3D = NULL;                                              
	pd3dDevice = NULL;
	MatrixStack = NULL;
	Vertex_Buffer = NULL;
	VertexDeclaration = NULL;

}

DxManager::~DxManager(void)
{

}

bool DxManager::initDirect3D(HWND hwnd,bool fullscreen)
{
	 // This object will allow us to set the display mode of the screen.
   D3DDISPLAYMODE DisplayMode;

   // This will allow us to set the parameters of the screen.
   D3DPRESENT_PARAMETERS Present_Parameters;

   // This is used to get the capabilities of the hardware.
   D3DCAPS9 D3DCaps;

   // It is always a good idea to clear out memory in object although not necessary.
   ZeroMemory(&Present_Parameters, sizeof(Present_Parameters));

   // Create the Direct3D object to get everything started.
   pD3D = Direct3DCreate9(D3D_SDK_VERSION);

   // Error checking.  Make sure that it was successful.
   if(pD3D == NULL)
      {
         MessageBox(NULL, "Error, couldn't initialize DirectX!?!",
                    "Error!", MB_OK);
         return false;
      }

   // This function will get the display mode of the device and place it in DisplayMode.
   if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DisplayMode)))
   {
       MessageBox(NULL, "Error setting the display mode.", "Error!", MB_OK);
       return false;
   }

   // Get the capabilities of the hardware.
   if(FAILED(pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps)))

		return false;

   // Test which is supported, hardware or software vertex processing.
	DWORD VertexProcessing = 0;

	if(D3DCaps.VertexProcessingCaps != 0)
		VertexProcessing |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		VertexProcessing |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

   // Here we are setting the applications parameters...
   if(fullscreen)  // TODO full screen Implmentation
   {
      Present_Parameters.Windowed = FALSE;               // Window mode (fullscreen).
      Present_Parameters.BackBufferWidth = DisplayMode.Width;
      Present_Parameters.BackBufferHeight = DisplayMode.Height;
   }
   else
   {
      Present_Parameters.Windowed = TRUE;                   // Window mode (not fullscreen).
	  Present_Parameters.BackBufferWidth = 640;
      Present_Parameters.BackBufferHeight = 480;
   }

   Present_Parameters.hDeviceWindow    = hwnd;
   Present_Parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;   // Dealing with animation (see doc).
   Present_Parameters.BackBufferFormat =DisplayMode.Format;// Render to the area of the screen.
   Present_Parameters.BackBufferCount = 1;                  // Number of back buffers.
   Present_Parameters.EnableAutoDepthStencil = TRUE;        // Check documentation.
   Present_Parameters.AutoDepthStencilFormat = D3DFMT_D16;  // Check documentation.

   // Now we must create the rendering device.
   if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
                        VertexProcessing, &Present_Parameters, &pd3dDevice)))
   {
		MessageBox(NULL, "CreateDevice() failed!  Make sure you have DirectX 9.",
                    "Error!", MB_OK);
        return false;
   }

   // One last check to be sure.
   if(pd3dDevice == NULL)
   {
        MessageBox(NULL, "pd3dDevice is equal to NULL!?!", "Error!", MB_OK);
        return false;
   }

    pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
    pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
    pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(55, 55, 55));
    pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE); 
    pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

    // Set the projection.

	D3DXCreateMatrixStack(0, &MatrixStack);

	return true;
}

void DxManager::beginRender(void)
{
	// call our render function
	pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );

	pd3dDevice->BeginScene();

	MatrixStack->LoadIdentity();
}

void DxManager::endRender(void)
{
	pd3dDevice->EndScene();

    pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

void DxManager::shutdown(void)
{
	if( pd3dDevice != NULL) 
	{
        pd3dDevice->Release();
		pd3dDevice = NULL;
	}
    if( pD3D != NULL)
	{
        pD3D->Release();
		pD3D = NULL;
	}

    // Here we release the Direct3D objects.
   delete[] Texture;
   delete[] LightMaps;
   Texture = NULL;
   LightMaps = NULL;

   if(Vertex_Buffer != NULL)
   {
		Vertex_Buffer->Release();
        Vertex_Buffer = NULL;
   }

   if(VertexDeclaration != NULL)
   {
        VertexDeclaration->Release();
        VertexDeclaration = NULL;
   }

   if(MatrixStack != NULL)
   {
	   MatrixStack->Release();
	   MatrixStack = NULL;
   }
}

// Function for getting the pd3dDevice since it's a private
// attribute of DxManager
LPDIRECT3DDEVICE9 DxManager::getDevice(void)
{
	return pd3dDevice;
}

D3DMATERIAL9 DxManager::getMat(void)
{
	return mtrl;
}


